﻿/************************************************************************
 * CoreDES - A small and core library for discrete event systems
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     CoreDES\Utils\Variable.cs
 * Description  :     
 * Change log   :     -Oct 2013: initial version
 * To Do        :
 ************************************************************************/
using System;
using System.Reflection;
using System.Collections.Generic;
using CoreDES.Execution;
using CoreDES.Modeling;

namespace CoreDES.Modeling
{
    /// <summary>
    /// The variable class which implements the interface 'IVariable'
    /// </summary>
    public class Variable :IVariable
    {
        string _ID, _Type, tag;
        FieldInfo info;
        public FieldInfo Info
        {
            get
            {
                return info;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"></param>
        public Variable(string id, string type, FieldInfo info = null)
        {
            this.info = info;
            this.tag = "Variable";
            _ID = id;
            _Type = type;
        }

        /// <summary>
        /// 
        /// </summary>
        public string Tag
        {
            get { return tag; }
        }

        #region Composed Event
        public class IDArgs : System.EventArgs
        {
            public string type;
            public string oldName;
            public string newName;

            public IDArgs(string t, string o, string n)
            {
                type = t;
                this.oldName = o;
                this.newName = n;
            }
        }

        public delegate void ChangingHandler(object sender, IDArgs va);
        public event ChangingHandler ChangeVariableID = null;

        public Variable Clone()
        {
            Variable newV = new Variable(this.ID, this._Type/*, this.variableTag*/);
            newV.ChangeVariableID = this.ChangeVariableID;
            return newV;
        }

        //Changed Based on Composed Model
        /// <summary>
        /// 
        /// </summary>
        public string ID
        {
            get
            {
                return _ID;
            }
            set
            {
                //ID = value;
                if (_ID != value && ChangeVariableID != null)
                {
                    IDArgs va = new IDArgs("variable", this._ID, value);
                    _ID = value;
                    ChangeVariableID(this, va);
                }
                else
                    _ID = value;


            }
        }

        /// <summary>
        /// 
        /// </summary>
        public string VariableType
        {
            get
            {
                return _Type;
            }
            set
            {
                //_Type = value;
                if (_Type != value && ChangeVariableID != null)
                {
                    IDArgs va = new IDArgs("variableType", this._Type, value);
                    _Type = value;
                    ChangeVariableID(this, va);
                }
                else
                    _Type = value;
            }
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        //[Browsable(false)]
        public string ProrammingVariableType
        {
            get
            {
                string type = VariableType;
                if (type.Contains("["))
                {
                    type = type.Substring(0, type.IndexOf('[')) + "[]";
                }

                return type;
            }
        }

        public override string ToString()
        {
            return _ID + ":" + VariableType;
        }

        //#region ICloneable Members

        //object ICloneable.Clone()
        //{
        //    throw new NotImplementedException();
        //}

        //#endregion

        #region IVariable Members

        public string Name
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }


    public class VaribalesCollection //: IFormalismElement
    {


        public delegate void InitializerHandler();

       

        #region internal variables
        /*protected*/
        List<Variable> _variables = new List<Variable>();
        /*protected*/
        InitializerHandler _initializerHandler;
        Function _initialzer;
        string tag;
        #endregion


        /// <summary>
        /// Constructor
        /// </summary>
        public VaribalesCollection()
        {
            this.tag = "Variables";
        }

        public string Tag
        {
            get { return tag; }
        }

       

        public Variable this[string varID]
        {
            get
            {
                foreach (Variable v in _variables)
                    if (v.ID == varID)
                    {
                        return v;
                    }
                return null;
            }
        }

        public void SetInitializerHandler(InitializerHandler initializer)
        {
            _initializerHandler = initializer;
        }


        public void RunInitializer()
        {
            _initializerHandler();
        }


        //[DisplayName("Initializer Function"), ReadOnly(false), Editor()]
        public Function Initilizer
        {
            get
            {
                return _initialzer;
            }
            set
            {
                _initialzer = value;
            }
        }


        public List<Variable> Variables
        {
            get
            {
                return _variables;
            }
        }

        public string ID
        {
            get { return "_Variables"; }
        }


      

        #region Composed Model
        //public void WriteXml(XmlDatabaseHelper db, XmlDatabaseHelper.XmlRow model)
        //{
        //    XmlDatabaseHelper.XmlRow row = model.AddXmlRow("Variables");
        //    foreach (Variable var in Variables)
        //    {
        //        XmlDatabaseHelper.XmlRow v = row.AddXmlRow("Variable");
        //        v.Attributes["ID"] = var.ID;
        //        v.Attributes["type"] = var.VariableType;

        //    }
        //    XmlDatabaseHelper.XmlRow i = row.AddXmlRow("Initializer");
        //    i.Attributes["type"] = "void";
        //    i.Value = Initilizer.Code;

        //}
        //public VaribalesCollection Clone()
        //{

        //    VaribalesCollection newVC = new VaribalesCollection();
        //    newVC.Initilizer = this.Initilizer.Clone();
        //    foreach (Variable v in this.Variables)
        //    {
        //        Variable newV = v.Clone();
        //        newVC.Variables.Add(newV);
        //    }
        //    return newVC;
        //}
        #endregion

        #region Code Generation
        /// <summary>
        /// For state space generation
        /// </summary>
        /// <returns></returns>
        public string GenerateCloneMethod()
        {
            return null;
        }

        /// <summary>
        /// For state space generation
        /// </summary>
        /// <returns></returns>
        public string GenerateEqualMethod()
        {
            return null;
        }

        /// <summary>
        /// Generate definion of a variable for the code generation part
        /// </summary>
        /// <returns>the generated code</returns>
        public string GenerateDefenition()
        {
            string code = "";
            foreach (Variable var in _variables)
            {

                if (true /*var.VariableTag == vartype.Variable*/)
                {
                    string type = "";
                    for (int i = 0; i < var.VariableType.Length; i++)
                    {
                        if (var.VariableType[i] == ' ' || var.VariableType[i] == '[')
                            break;
                        type += var.VariableType[i];
                    }
                    //if(var.VariableType.Contains("["))
                    //     type = var.VariableType.Substring(0, var.VariableType.IndexOf('[')); 
                    //else
                    //    type=var.VariableType;
                    string createvar = ";";
                    if (var.VariableType.Contains("["))
                    {

                        //if ((type == "int") || (type == "byte") || (type == "uint") || (type == "ushort")
                        //    || (type == "short") || (type == "double") || (type == "float") || (type == "bool"))
                        //{
                        bool sizeIsSpecified = false;
                        for (int i = var.VariableType.IndexOf("[") + 1; i <= var.VariableType.IndexOf("]") - 1; i++)
                        {
                            if (var.VariableType[i] != ',' && var.VariableType[i] != ' ')
                            {
                                sizeIsSpecified = true;
                                break;
                            }
                        }
                        if (sizeIsSpecified)
                            if (var.VariableType.LastIndexOf("[") > var.VariableType.IndexOf("]"))
                                createvar = " = new " + var.VariableType + ";";//+ "[][];";
                            else //if (type.Contains("]["))
                                createvar = " = new " + var.VariableType + ";";// +"[];";
                        //}
                    }
                    //if (type == "int" || type == "byte" || type == "uint" ||
                    //        type == "ushort" || type == "short" || type == "double" || type == "float" || type == "bool")
                    //{
                    type = "";
                    for (int i = 0; i < var.VariableType.Length; i++)
                    {

                        if (var.VariableType[i] == '[')
                        {
                            type += var.VariableType[i];
                            do
                            {
                                i++;
                                if (var.VariableType[i] == ',' || var.VariableType[i] == ']' || var.VariableType[i] == '[')
                                    type += var.VariableType[i];

                            } while (i < var.VariableType.Length && var.VariableType[i] != ']');
                        }
                        else
                            type += var.VariableType[i];
                    }
                    code += "\n\tpublic " + type + " " + var.ID + createvar;
                    //}
                    //else
                    //    code += "public " + var.VariableType + " " + var.ID + createvar;
                    //int a[4];

                }
                //else if (var.VariableTag == vartype.Set)
                //{
                //    string type = var.VariableType;
                //    string createvar = "= MyList<" + type + ">();";
                //    code += "MyList<" + type + "> "
                //        + var.ID + createvar;
                //}
            }
            return code;
        }
        #endregion
	
    }
}